"""
NAME:
  string2radec
PURPOSE:
  Code for string transformation of coordinates
FUNCTIONS:
  string2radec()
  radec2string()
"""

__author__ = 'Michael Blanton <michael.blanton@gmail.com>'

__version__ = '$Revision: 8 $'.split(': ')[1].split()[0]

__all__ = [ 'string2radec', 'radec2string']

#
# Modules
#
import re
from math import *
from numpy import *

#
# Classes
#
        
#
# Functions
#
def string2radec(string):
    """
    NAME:
      string2radec
    PURPOSE
      Converting from a string to ra and dec
    CALLING SEQUENCE:
      (ra, dec)= string2radec(string)
    COMMENTS:
      Converts any string of the following forms to decimal:
       HH MM SS[.S] [+|-]DD MM SS[.S]
       HH:MM:SS[.S] [+|-]DD:MM:SS[.S]
       HHMMSS[.S][+|-]DDMMSS[.S]
      It returns an (ra, dec) tuple.  For non-valid strings, or
      coordinates out of range, it retuns None.
    AUTHOR:
      Mike Blanton, NYU 2009-10-31
    """

    # Parse the string into elements
    div='(|:|\s)'
    sra='(\d\d)'+div+'(\d\d)'+div+'(\d\d)(\.?\d*|)'
    sdec='(\s*|\s*\+|\s*\-)'+'(\d\d)'+div+'(\d\d)'+div+'(\d\d)(\.?\d*|)'
    sradec= sra+sdec
    co_re= re.compile(sradec)
    co_search= co_re.search(string)
    if(co_search is None):
        return 
    elems=co_search.groups()
    
    # Check for nonsense values
    if(double(elems[0])>24.):
        return
    if(double(elems[2])>=60.):
        return
    if(double(elems[4])>=60.):
        return
    if(double(elems[7])>90.):
        return
    if(double(elems[9])>=60.):
        return
    if(double(elems[11])>=60.):
        return

    # Convert ra
    ra= (double(elems[0])*double(15.)+
         double(elems[2])*double(15./60.)+
         double(elems[4])*double(15./3600.))
    if(elems[5] != '' and elems[5] != '.'):
        ra=ra+double(elems[5])*double(15./3600.)
    if(ra>360.):
        return 

    # Convert dec
    dec= (double(elems[7])+
          double(elems[9])/double(60.)+
          double(elems[11])/double(3600.))
    if(elems[12] != '' and elems[12] != '.'):
        dec=dec+double(elems[12])/double(3600.)
    if(dec>90.):
        return
    if(re.match('\s*\-', elems[6])):
        dec=double(-1.)*dec
        
    return (ra, dec)

def radec2string(ra, dec, sep=':', nsig=2):
    """
    NAME:
      radec2string
    PURPOSE
      Converting from ra and dec to a string
    CALLING SEQUENCE:
      string= radec2string(ra, dec [, sep=, nsig=] )
    INPUTS:
      ra, dec - decimal ra, dec in deg
    OPTIONAL INPUTS:
      sep - separator string (default ':')
      nsig - number of digits past decimal in RA (default 2)
    COMMENTS:
      Converts decimal ra and dec to form:
         HH:MM:SS.SS[+/-]DD:MM:SS.S
      Optional argument 'sep' specifies separator (default ':')
      Optional argument 'nsig' specifies number of decimal digits in RA
        (default 2); one less used for Dec
      Coordinates are TRUNCATED not ROUNDED
    AUTHOR:
      Mike Blanton, NYU 2009-10-31
    """

    if(nsig<=0):
        nsigra=0
        nsigdec=0
    else:
        nsigra=nsig
        nsigdec=nsig-1

    rahr= long(ra/15.)
    ramin= long((ra/15.- double(rahr))*60.)
    rasec= ((ra/15.- double(rahr))*60.- double(ramin))*60.
    rasec= double(long(rasec*pow(10., nsigra))/pow(10., nsigra))

    if(dec<0.):
        decsign='-'
    else:
        decsign='+'
    adec=abs(dec)
    decdeg= long(adec)
    decmin= long((double(adec)- double(decdeg))*60.)
    decsec= ((double(adec)- double(decdeg)- double(decmin)/60.)*3600.)
    decsec= double(long(decsec*pow(10., nsigdec))/pow(10., nsigdec))

    if(nsigra==0):
        fra="%02d"
    else:
        fra="%0"+str(nsigra+3)+"."+str(nsigra)+"f"
    if(nsigdec==0):
        fdec="%02d"
    else:
        fdec="%0"+str(nsigdec+3)+"."+str(nsigdec)+"f"

    rastr= "%02d"+sep+"%02d"+sep+fra
    rastr= rastr % (rahr, ramin, rasec)
    decstr= decsign+"%02d"+sep+"%02d"+sep+fdec
    decstr= decstr % (decdeg, decmin, decsec)

    return rastr+decstr
    
#
# Unit tests
#
if __name__ == '__main__':
    print "Testing string2radec->radec2string"
    sts= ['05:33:22.54+89:00:01.4',
          '05:33:22.54 89:00:01.4',
          '05:33:22.5489:00:01.4',
          '053322.54 890001.4',
          '23:22:00.34-00:30:33.2',
          '232200.34-003033.2',
          '12:55:10.34-30:10:37.2']
    for st in sts:
          (ra, dec)= string2radec(st)
          stback= radec2string(ra, dec)
          print st, "->", ra, dec, "->", stback
    

